package com.mygame.center.controller;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Base64Utils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.mygame.center.dataconfig.GameGatewayInfo;
import com.mygame.center.service.GameGatewayService;
import com.mygame.center.service.PlayerService;
import com.mygame.center.service.UserLoginService;
import com.mygame.common.error.GameErrorException;
import com.mygame.common.error.IServerError;
import com.mygame.common.error.TokenException;
import com.mygame.common.utils.JWTUtil;
import com.mygame.common.utils.JWTUtil.TokenBody;
import com.mygame.common.utils.RSAUtils;
import com.mygame.db.entity.Player;
import com.mygame.db.entity.UserAccount;
import com.mygame.db.entity.UserAccount.ZonePlayerInfo;
import com.mygame.error.GameCenterError;
import com.mygame.http.MessageCode;
import com.mygame.http.request.CreatePlayerParam;
import com.mygame.http.request.LoginParam;
import com.mygame.http.request.SelectGameGatewayParam;
import com.mygame.http.response.GameGatewayInfoMsg;
import com.mygame.http.response.LoginResult;
import com.mygame.http.response.ResponseEntity;

@RestController
@RequestMapping("/request")
public class UserController {
	@Autowired
	private UserLoginService userLoginService;
	@Autowired
	private GameGatewayService gameGatewayService;
	@Autowired
	private PlayerService playerService;

	private Logger logger = LoggerFactory.getLogger(UserController.class);

	@PostMapping(MessageCode.USER_LOGIN)
	public ResponseEntity<LoginResult> login(@RequestBody LoginParam loginParam) {
		loginParam.checkParam();// 检测请求参数的合法性
		IServerError serverError = userLoginService.verfiySdkToken(loginParam.getOpenId(), loginParam.getToken());
		if (serverError != null) {// 请求第三方，验证登陆信息的正确性
			throw GameErrorException.newBuilder(serverError).build();
		}
		UserAccount userAccount = userLoginService.login(loginParam);
		LoginResult loginResult = new LoginResult();
		loginResult.setUserId(userAccount.getUserId());
		String token = JWTUtil.getUsertoken(userAccount.getOpenId(), userAccount.getUserId());
		loginResult.setToken(token);// 这里使用JWT生成Token
		logger.debug("user {} 登陆成功", userAccount);
		return new ResponseEntity<LoginResult>(loginResult);
	}

	@PostMapping(MessageCode.CREATE_PLAYER)
	public ResponseEntity<ZonePlayerInfo> createPlayer(@RequestBody CreatePlayerParam param,
			HttpServletRequest request) {
		param.checkParam();
		String token = request.getHeader("token");// 从http包头里面获取token的值
		if (token == null) {
			throw GameErrorException.newBuilder(GameCenterError.TOKEN_FAILED).build();
		}
		TokenBody tokenBody;
		try {
			tokenBody = JWTUtil.getTokenBody(token);// 从加密的token中获取明文信息
		} catch (TokenException e) {
			throw GameErrorException.newBuilder(GameCenterError.TOKEN_FAILED).build();
		}
		String openId = tokenBody.getOpenId();
		// 使用网关之后，就可以在这里直接获取openId，网关那边会自动验证权限，如果没有使用网关，需要打开上面注释，并注释掉下面这行代码。
		// String openId = userLoginService.getOpenIdFromHeader(request);
		UserAccount userAccount = userLoginService.getUserAccountByOpenId(openId).get();
		String zoneId = param.getZoneId();
		ZonePlayerInfo zoneInfo = userAccount.getZonePlayerInfo().get(zoneId);
		if (zoneInfo == null) {
			Player player = playerService.createPlayer(param.getZoneId(), param.getNickName());
			zoneInfo = new ZonePlayerInfo(player.getPlayerId(), System.currentTimeMillis());
			userAccount.getZonePlayerInfo().put(zoneId, zoneInfo);
			userLoginService.updateUserAccount(userAccount);
		}
		ResponseEntity<ZonePlayerInfo> response = new ResponseEntity<ZonePlayerInfo>(zoneInfo);
		return response;
	}

	@PostMapping(MessageCode.SELECT_GAME_GATEWAY)
	public Object selectGameGateway(@RequestBody SelectGameGatewayParam param) throws Exception {
		param.checkParam();
		long playerId = param.getPlayerId();
		GameGatewayInfo gameGatewayInfo = gameGatewayService.getGameGatewayInfo(playerId);
		GameGatewayInfoMsg gameGatewayInfoMsg = new GameGatewayInfoMsg(gameGatewayInfo.getId(), gameGatewayInfo.getIp(),
				gameGatewayInfo.getPort());
		Map<String, Object> keyPair = RSAUtils.genKeyPair();// 生成rsa的公钥和私钥
		byte[] publickKeyBytes = RSAUtils.getPublicKey(keyPair);// 获取公钥
		String publickKey = Base64Utils.encodeToString(publickKeyBytes);// 为了方便传输，对bytes数组进行一下base64编码
		String token = playerService.createToken(param, gameGatewayInfo.getIp(), publickKey);// 根据这些参数生成token
		gameGatewayInfoMsg.setToken(token);
		byte[] privateKeyBytes = RSAUtils.getPrivateKey(keyPair);
		String privateKey = Base64Utils.encodeToString(privateKeyBytes);
		gameGatewayInfoMsg.setRsaPrivateKey(privateKey);// 给客户端返回私钥
		logger.debug("player {} 获取游戏网关信息成功：{}", playerId, gameGatewayInfoMsg);
		ResponseEntity<GameGatewayInfoMsg> responseEntity = new ResponseEntity<>(gameGatewayInfoMsg);
		return responseEntity;
	}

}
